package com.example.transaction.service.bussiness.impl;

import com.example.transaction.entity.Step;
import com.example.transaction.service.bussiness.IStepFlowService;
import com.example.transaction.service.common.IStepCommonService;
import com.example.transaction.state.StepStateMachine;
import com.example.transaction.vo.StepStateVO;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.function.Consumer;

@Scope("request")
@Service
public class StepFlowServiceImpl implements IStepFlowService {


    @Autowired
    private StepStateMachine stepStateMachine;

    @Autowired
    private IStepCommonService stepCommonService;

    @Override
    @Transactional
    public void flow(StepStateVO request) {
        Step step = stepCommonService.getById(request.getStepId());
        getExecutor(request.getAction()).accept(step);
    }

    /**
     * 由于此处使用this的内部调用 会导致被调用的方法代理失败 进而导致方法上的事务注解失效
     * 如果要内部调用则需要 AopContext.currentProxy()并在启动类开启@EnableAspectJAutoProxy(exposeProxy = true)
     * 普通内部调用的被调用方法事务注解失效
     */
    private Consumer<Step> getExecutor(String action) {
        if ("start".equals(action)) {
            return this::start;
        }
        if ("finish".equals(action)) {
            return this::finish;
        }
        if ("fail".equals(action)) {
            return this::fail;
        }
        if ("skip".equals(action)) {
            return this::skip;
        }
        if ("approve".equals(action)) {
            return this::approve;
        }
        if ("rollback".equals(action)) {
            return this::rollback;
        }
        throw new RuntimeException("未定义的操作");
    }

    public void start(Step step) {
        if (permissionDenied(true, true, "executor")) {
            throw new RuntimeException();
        }
        stepStateMachine.start(step);
    }

    public void finish(Step step) {
        if (permissionDenied(true, true, "admin")) {
            throw new RuntimeException();
        }
        stepStateMachine.finish(step);
        headman(step);
    }

    /**
     * 此处 @Transactional加了无用 因为上方代码 skip被使用时是通过this内部调用导致代理失效了 事务注解失效
     * 如果是外部类直接调用skip方法则不会
     */
    public void skip(Step step) {
        if (permissionDenied(true, true, "admin")) {
            throw new RuntimeException();
        }
        stepStateMachine.skip(step);
        headman(step);
    }

    public void fail(Step step) {
        if (permissionDenied(true, true, "admin")) {
            throw new RuntimeException();
        }
        stepStateMachine.fail(step);
        headman(step);
    }

    public void approve(Step step) {
        if (permissionDenied(false, true, "admin")) {
            throw new RuntimeException();
        }
        stepStateMachine.approve(step);
    }

    public void rollback(Step step) {
        if (permissionDenied(false, false, "admin")) {
            throw new RuntimeException();
        }
        stepStateMachine.rollback(step);
    }

    private boolean permissionDenied(boolean excutor, boolean reviewer, String current) {
        if ("admin".equals(current)) {
            return false;
        }
        if (excutor && "executor".equals(current)) {
            return false;
        }
        if (reviewer && "reviewer".equals(current)) {
            return false;
        }
        return true;
    }

    public void headman(Step step) {
        if (permissionDenied(false, false, "admin")) {
            return;
        }
        stepStateMachine.approve(step);
    }

}
